//
//  MKLabel.m
//  YYTextS
//
//  Created by Burn on 2019/9/10.
//  Copyright © 2019 menksoft. All rights reserved.
//

#import "MKLabel.h"
#import <CoreText/CoreText.h>

@interface MKLabel ()
@property (nonatomic, strong) NSMutableAttributedString *attributedText;
@property(assign,nonatomic) NSInteger textRealLine;

@property(assign,nonatomic) CGFloat textWidth;
@property(assign,nonatomic) CGFloat textHeight;
@property(assign,nonatomic) CGFloat lineAscent;
@property(assign,nonatomic) CGFloat lineDescent;
@property(assign,nonatomic) CGFloat lineLeading;


@end


@implementation MKLabel

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    
    [self updateAttributedText];    //  这里应该是设置字体和,字的方向
    //获取画布句柄
    CGContextRef context = UIGraphicsGetCurrentContext();
    //颠倒窗口 坐标计算使用的mac下的坐标系 跟ios的坐标系正好颠倒   下满三行代码主要就是颠倒  坐标好像是macOS来算的所以需要颠倒  注释三行代码就可以看到结果了
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    
    //生成富文本的信息 具体不懂  反正这是core text绘制的必须流程和对象
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self.attributedText);
    //这一步生成合适的绘制区域
    CGPathRef path = [self createPathWithLines];
//    CGPathRef path1 = CGPathCreateWithRect(CGRectMake(10, 10, self.bounds.size.width - 20, self.bounds.size.height - 20), nil);
    
    // Create a frame for this column and draw it.
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter,
                                                CFRangeMake(0, 0),
                                                path,
                                                (CFDictionaryRef)@{(id)kCTFrameProgressionAttributeName: @(kCTFrameProgressionLeftToRight)});
    CTFrameDraw(frame, context);
    
    //释放内存
    CFRelease(frame);
    CFRelease(path);
    CFRelease(framesetter);
}


-(void)updateAttributedText{
    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:self.text attributes:nil];
    
//    for (int i = 0; i < attrStr.length; i++) {
//        if ([self isChinese:self.text index:i]) {
//            [attrStr addAttribute:(id)kCTVerticalFormsAttributeName
//                            value:@YES
//                            range:NSMakeRange(i, 1)];
//            [attrStr addAttribute:NSKernAttributeName value:@(self.wordSpace) range:NSMakeRange(i, 1)];
//        }
//    }
    
    //  蒙文设置这个 会断开
    //  [attrStr addAttribute:NSKernAttributeName value:@(self.wordSpace) range:NSMakeRange(0, self.text.length)];
    
    //为所有文本设置字体
    if (self.font) {
        CTFontRef fontRef = CTFontCreateWithName((CFStringRef)self.font.fontName, self.font.pointSize, NULL);
        // Set the lineSpacing.
        CGFloat lineSpacing = CTFontGetLeading(fontRef) + self.lineSpace;
        // Create the paragraph style settings.
        CTParagraphStyleSetting setting;
        setting.spec = kCTParagraphStyleSpecifierLineSpacing;
        setting.valueSize = sizeof(CGFloat);
        setting.value = &lineSpacing;
        CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(&setting, 1);
        [attrStr addAttribute:(NSString *)kCTFontAttributeName
                        value:(__bridge id _Nonnull)(fontRef)
                        range:NSMakeRange(0, [attrStr length])];
        [attrStr addAttribute:(id)kCTParagraphStyleAttributeName
                        value:(__bridge id)paragraphStyle
                        range:NSMakeRange(0, [attrStr length])];
        CFRelease(fontRef);
        CFRelease(paragraphStyle);
    }
    
    if (self.textColor) {
        //设置颜色
        [attrStr addAttribute:(NSString *)kCTForegroundColorAttributeName
                        value:(__bridge id _Nonnull)(self.textColor.CGColor)
                        range:NSMakeRange(0,attrStr.length)];
    }
    
    self.attributedText = attrStr;
    [self caculateRealLine];
    [self setNeedsDisplay];
}


//计算富文本绘制真实产生的行数 以及文本显示的rect的宽高
-(void)caculateRealLine{
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self.attributedText);
    CGMutablePathRef path = CGPathCreateMutable();//创建一个path句柄
    CGPathAddRect(path, NULL, CGRectMake(_contentInsets.left, _contentInsets.top, self.bounds.size.width - _contentInsets.left, self.bounds.size.height - (_contentInsets.top + _contentInsets.bottom)));
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter,
                                                CFRangeMake(0, 0),
                                                path,
                                                (CFDictionaryRef)@{(id)kCTFrameProgressionAttributeName: @(kCTFrameProgressionLeftToRight)});
    
    CFArrayRef lines = CTFrameGetLines(frame); //lines指向的指针是frame的属性 不能释放 否则释放frame时会过渡释放
    self.textRealLine = CFArrayGetCount(lines); //we should always set textRealLine before we user self.numberOfLines
    self.textHeight = 0;
    self.textWidth = 0;
    for (int i = 0; i < self.numberOfLines; i++) {
        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
        CGFloat height = CTLineGetTypographicBounds(line, &_lineAscent, &_lineDescent, &_lineLeading);
        if (self.textHeight < height) {
            self.textHeight = height;
        }
        /**根据苹果官方说法https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/TypoFeatures/TextSystemFeatures.html#//apple_ref/doc/uid/TP40009459-CH6-BBCFAEGE
         *大部分文字的显示区域应该是处于lineAscent 但是根据我debug得到的数据lineDescent正好是一个汉字的宽度 lineAscent跟lineDescent有关 具体关系不清楚
         *所以我有理由相信竖向显示汉字的区域处于lineDescent，但是行高的计算还是需要加上lineAscent 尽管貌似lineAscent区域没有绘制，或者lineAscent区域只绘制英文？
         *再有lineLeading,根据http://geeklu.com/2013/03/core-text/ 这篇博客说lineLeading就是行间距，但是只是在竖向显示时，这个lineLeading一直是0，所以我们需要额外加上行间距
         **/
        _textWidth = _textWidth + _lineDescent + _lineAscent + _lineLeading + self.lineSpace;
        _textWidth =  _textWidth > self.bounds.size.width - _contentInsets.left - _contentInsets.right ? self.bounds.size.width - _contentInsets.left - _contentInsets.right : _textWidth;
    }
    CFRelease(frame);
    CFRelease(path);
    CFRelease(framesetter);
}


//  这一步生成合适的绘制区域 默认规则是居中
- (CGPathRef)createPathWithLines
{
    // 居中显示 计算中间的矩形
    CGFloat startX = self.bounds.origin.x;//default x, y
    CGFloat startY = self.bounds.origin.y;
    if (self.baseLine == MKTextAlignmentCenter) {
        //居中显示
        startX = (self.bounds.size.width - _textWidth ) * 0.5;
        startY = (self.bounds.size.height - _textHeight) * 0.5;
    }else{
        //需要注意！！！！！！！！这里计算的区域Y坐标是mac坐标系下的坐标
        startX = _contentInsets.left;
        startY = _contentInsets.bottom;
        if (_contentInsets.right != 0 && _contentInsets.left == 0) {
            startX = self.bounds.size.width - _textWidth - _contentInsets.right;
            
        }
    }
    
    //  这里注意的是 MacOS 和iOS的坐标系是颠倒的  所以y使用 _contentInsets.bottom
    //  CGRect contentRect = CGRectMake(_contentInsets.left, _contentInsets.bottom, _textWidth, self.bounds.size.height - _contentInsets.top - _contentInsets.bottom);
    
    
    CGRect contentRect = CGRectMake(startX, startY, _textWidth, _textHeight);
    NSLog(@"==%@",NSStringFromCGRect(contentRect));
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, contentRect);
    return path;
}


-(NSInteger)numberOfLines{
    return _numberOfLines > 0 ? (_numberOfLines > self.textRealLine ? self.textRealLine : _numberOfLines) : self.textRealLine;
}



-(void)setText:(NSString *)text{
    if (text && ![self.text isEqualToString:text]) {
        _text = [text stringByAppendingString:text];
        [self setNeedsDisplay];
    }else{
        _text = text;
    }
}


-(void)layoutSubviews{
    [super layoutSubviews];
    [self setNeedsDisplay];
}

@end
